#!/usr/bin/env bun

/* eslint-disable security/detect-non-literal-fs-filename */

/**
 * 覆盖率报告生成器 - 统一入口
 *
 * 这个脚本提供了一个统一的入口来生成HTML格式的测试覆盖率报告。
 * 它会运行测试、生成LCOV数据，然后创建美观的HTML报告。
 *
 * 使用方法:
 *   bun run scripts/coverage/index.ts [options]
 *
 * 选项:
 *   -o, --output <dir>     输出目录 (默认: coverage)
 *   -c, --clean           清理之前的报告
 *   --open                生成后自动打开报告
 *   -t, --threshold <num>  覆盖率阈值百分比 (默认: 80)
 *   -h, --help            显示帮助信息
 */

import { existsSync, mkdirSync, rmSync, writeFileSync, readFileSync } from 'fs';
import { join, resolve } from 'path';

import { $ } from 'bun';
import { Command } from 'commander';

import { LcovParser, HtmlReportGenerator } from './html-generator';

const program = new Command();

interface CoverageOptions {
  output: string;
  clean: boolean;
  open: boolean;
  threshold: number;
}

program
  .name('coverage')
  .description('生成HTML测试覆盖率报告')
  .version('1.0.0')
  .option('-o, --output <dir>', '输出目录', 'coverage')
  .option('-c, --clean', '清理之前的报告', false)
  .option('--open', '生成后自动打开报告', false)
  .option('-t, --threshold <number>', '覆盖率阈值百分比', '80')
  .parse();

const options = program.opts<CoverageOptions>();

// 验证阈值参数
const threshold = parseInt(options.threshold.toString());
if (isNaN(threshold) || threshold < 0 || threshold > 100) {
  console.error('❌ 错误: 阈值必须是 0-100 之间的数字');
  process.exit(1);
}

console.log('🚀 开始生成HTML覆盖率报告...');
console.log(`📁 输出目录: ${options.output}`);
console.log(`🎯 覆盖率阈值: ${threshold}%`);

try {
  // 清理之前的报告（但保留 lcov.info）
  if (options.clean && existsSync(options.output)) {
    console.log('🧹 清理之前的报告...');
    // 只清理HTML报告文件，保留 lcov.info
    const htmlDir = join(options.output, 'html');

    if (existsSync(htmlDir)) {
      rmSync(htmlDir, { recursive: true, force: true });
    }
  }

  // 确保输出目录存在
  if (!existsSync(options.output)) {
    mkdirSync(options.output, { recursive: true });
  }

  // 如果输出目录不是 coverage，则清理默认的 coverage 目录中的旧数据
  if (options.output !== 'coverage' && existsSync('coverage')) {
    rmSync('coverage', { recursive: true, force: true });
  }

  // 运行测试并生成 lcov 报告
  console.log('🧪 运行测试并生成 lcov 报告...');
  try {
    await $`bun test --coverage --coverage-reporter=lcov`;
  } catch {
    console.warn('⚠️  测试可能失败，但继续生成覆盖率报告...');
  }

  // 检查 lcov 文件是否存在
  const defaultLcovPath = 'coverage/lcov.info';
  if (!existsSync(defaultLcovPath)) {
    console.error('❌ 错误: 未找到 lcov.info 文件，请确保测试正确运行');
    process.exit(1);
  }

  // 如果输出目录不是 coverage，复制 lcov.info 到输出目录
  let lcovPath = defaultLcovPath;
  if (options.output !== 'coverage') {
    lcovPath = join(options.output, 'lcov.info');
    const lcovContent = readFileSync(defaultLcovPath, 'utf8');
    writeFileSync(lcovPath, lcovContent);
  }

  console.log('✅ lcov 报告生成成功');

  // 生成 HTML 报告
  console.log('📄 生成 HTML 覆盖率报告...');
  const htmlOutputDir = join(options.output, 'html');

  try {
    // 创建HTML输出目录
    if (!existsSync(htmlOutputDir)) {
      mkdirSync(htmlOutputDir, { recursive: true });
    }

    // 读取并解析 lcov 文件
    const lcovContent = readFileSync(lcovPath, 'utf8');
    const records = LcovParser.parse(lcovContent);

    // 生成自定义 HTML 报告
    HtmlReportGenerator.generate(records, htmlOutputDir);

    console.log(`✅ HTML 报告生成成功: ${htmlOutputDir}/index.html`);

    // 自动打开报告
    if (options.open) {
      const htmlFile = resolve(join(htmlOutputDir, 'index.html'));
      if (existsSync(htmlFile)) {
        console.log('🌐 正在打开 HTML 报告...');
        try {
          // 跨平台打开文件
          const { platform } = process;
          if (platform === 'win32') {
            await $`cmd /c start "" "${htmlFile}"`;
          } else if (platform === 'darwin') {
            await $`open "${htmlFile}"`;
          } else {
            // Linux 和其他 Unix-like 系统
            await $`xdg-open "${htmlFile}"`;
          }
        } catch {
          console.log(`请手动打开: ${htmlFile}`);
        }
      }
    }
  } catch (error) {
    console.error('❌ HTML 报告生成失败:', error);
    process.exit(1);
  }

  // 显示覆盖率摘要
  console.log('\n📊 生成覆盖率摘要...');
  try {
    // 使用我们的解析器生成摘要
    const lcovContent = readFileSync(lcovPath, 'utf8');
    const records = LcovParser.parse(lcovContent);
    const summary = LcovParser.generateSummary(records);

    console.log('\n===========================================');
    console.log('            📊 覆盖率摘要');
    console.log('===========================================');
    console.log(
      `📝 代码行覆盖率:  ${summary.lines.percent.toFixed(2)}% (${summary.lines.hit}/${summary.lines.found})`
    );
    console.log(
      `🔧 函数覆盖率:    ${summary.functions.percent.toFixed(2)}% (${summary.functions.hit}/${summary.functions.found})`
    );
    console.log(
      `🌿 分支覆盖率:    ${summary.branches.percent.toFixed(2)}% (${summary.branches.hit}/${summary.branches.found})`
    );
    console.log('===========================================');

    // 检查覆盖率阈值
    const coveragePercent = summary.lines.percent;
    if (coveragePercent >= threshold) {
      console.log(
        `✅ 覆盖率 ${coveragePercent.toFixed(2)}% 达到了阈值 ${threshold}%`
      );
    } else {
      console.log(
        `⚠️  覆盖率 ${coveragePercent.toFixed(2)}% 未达到阈值 ${threshold}%`
      );
      process.exit(1);
    }
  } catch (error) {
    console.warn('⚠️  无法生成覆盖率摘要:', error);
  }

  console.log('\n🎉 HTML覆盖率报告生成完成!');
  console.log(`📁 报告位置: ${htmlOutputDir}/index.html`);
} catch (error) {
  console.error('❌ 生成覆盖率报告时发生错误:', error);
  process.exit(1);
}
